package com.donleo.stmg.aop;

import com.donleo.stmg.common.api.CommonResult;
import com.donleo.stmg.entity.model.User;
import com.donleo.stmg.entity.service.RedisService;
import com.donleo.stmg.entity.service.UserService;
import com.donleo.stmg.entity.vo.LoginParams;
import com.donleo.stmg.relation.mapper.UserLoginRecordMapper;
import com.donleo.stmg.relation.model.UserLoginRecord;
import com.donleo.stmg.relation.vo.EsUserLoginRecordVo;
import com.donleo.stmg.repository.EsUserLoginRecordRepository;
import com.donleo.stmg.utils.CommonPath;
import com.donleo.stmg.utils.DateUtil;
import com.donleo.stmg.utils.IpUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author liangd
 * date 2020-12-21 19:32
 * code 记录用户登录日志
 */
@Aspect
@Component
@Order(1)
public class UserAspect {

    @Autowired
    private UserLoginRecordMapper userLoginRecordMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private EsUserLoginRecordRepository esUserLoginRecordRepository;

    /**
     * 配置切点方法
     */
    @Pointcut("execution(public * com.donleo.stmg.entity.controller.UserController.login(..))")
    public void pointCut() {
    }

    /**
     * 判断用户是否被冻结
     */
    @Before(value = "pointCut()")
    public void userLoginLogs(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        LoginParams loginParams = (LoginParams) args[0];

        String userCode = loginParams.getCode();
        User user = userService.getUserByCode(userCode);
        //判断 redis 中有无loginFailTag标识符,再判断redis中是否有登录失败次数，两者条件同时满足才更改用户启用状态
        boolean b = redisService.hasKey("user::loginFailTag:" + userCode);
        if (!b) {
            boolean b1 = redisService.hasKey("user::loginFailCount:" + userCode);
            if (b1) {
                user.setDataEnable(CommonPath.YES.getValue());
                userService.frozenUser(user);
            }
        }
    }

    /**
     * 用户验证三次失败冻结账户
     */
    @AfterReturning(value = "pointCut()", returning = "result")
    public void userLoginFailedLogs(JoinPoint joinPoint, Object result) {
        Object[] args = joinPoint.getArgs();
        LoginParams loginParams = (LoginParams) args[0];
        HttpServletRequest request = (HttpServletRequest) args[1];
        //获取ip
        String ip = IpUtil.getIp(request);
        String userCode = loginParams.getCode();
        CommonResult commonResult = (CommonResult) result;
        long code = commonResult.getCode();
        User user = userService.getUserByCode(userCode);
        if (code == 404) {
            Integer loginFailCount;
            boolean hasKey = redisService.hasKey("user::loginFailCount:" + userCode);
            if (hasKey) {
                loginFailCount = (Integer) redisService.get("user::loginFailCount:" + userCode);
            } else {
                loginFailCount = 0;
            }

            loginFailCount++;
            //记录登录失败次数
            redisService.set("user::loginFailCount:" + userCode, loginFailCount);
            //设置过期时间 1小时
            if (loginFailCount == 1) {
                redisService.set("user::loginFailTime:" + userCode, DateUtil.getCurrentTime(), 60 * 60);
            }
            //判断登录失败次数是否大于3次
            if (loginFailCount > 3) {
                boolean b = redisService.hasKey("user::loginFailTime:" + userCode);
                //如果在1小时内登录失败三次，冻结用户
                if (b) {
                    user.setDataEnable(CommonPath.NO.getValue());
                    Assert.notNull(user.getId(), "Id is not to be null");
                    userService.frozenUser(user);
                    //用户登录失败次数三次以上，以用户编号为标识符，冻结用户24小时
                    redisService.set("user::loginFailTag:" + userCode, user.getCode(), 24 * 60 * 60);
                }
            }
        }
        //登录成功，删除登录失败记录
        if (code == 200) {
            boolean b1 = redisService.hasKey("user::loginFailTag:" + userCode);
            boolean b2 = redisService.hasKey("user::loginFailCount:" + userCode);
            boolean b3 = redisService.hasKey("user::loginFailTime:" + userCode);
            if (b1) {
                redisService.del("user::loginFailTag:" + userCode);
            }
            if (b2) {
                redisService.del("user::loginFailCount:" + userCode);
            }
            if (b3) {
                redisService.del("user::loginFailTime:" + userCode);
            }

            //将用户登录地址等信息存进数据库
            UserLoginRecord record = new UserLoginRecord();
            record.setIp(ip);
            record.setUserCode(userCode);
            record.setUsername(user.getUsername());
            record.setLoginTime(new Date());
            userLoginRecordMapper.insert(record);

            //存进es中
//            EsUserLoginRecordVo esUserLoginRecordVo = new EsUserLoginRecordVo();
//            BeanUtils.copyProperties(record,esUserLoginRecordVo);
//            esUserLoginRecordVo.setLoginTime(DateUtil.addTime(esUserLoginRecordVo.getLoginTime()));
//            esUserLoginRecordRepository.save(esUserLoginRecordVo);
        }

    }

}
